# -*- coding: utf-8 -*-
# @Date：2024/10/3 20:37:19
# @Author：CJiaの青姝
# @FileName：version
# @Editor：PyCharm2024
# @Remark：
from typing import Any, List
from typing_extensions import Self

from application.models import AppDetails, AppVersion
from ninja import Router, Field, Query, Schema, ModelSchema

from utils.cj_ninja import CjFilters
from utils.cj_compare import compare_version
from utils.cj_crud import create, delete, update, retrieve, single
from utils.cj_response import SuccessResponse, ErrorResponse

router = Router()


class Filters(CjFilters):
    versionCode: str = Field(None, description="应用版本号", alias='versionCode')
    app_id: int = Field(..., description="应用详情ID", alias='app_id')

    class Config:
        title = "应用版本查询参数"


class AppVersionSchemaIn(ModelSchema):
    app_id: int = Field(None, description="应用详情ID", alias='app_id')

    def validate(cls, value: Any) -> Self:
        if value.versionCode == '' or value.versionCode is None:
            return "版本号不能为空", 400
        elif value.apkUrl == '' or value.apkUrl is None:
            return "apk下载地址不能为空", 400
        elif value.wgtUrl == '' or value.wgtUrl is None:
            return "wgt下载地址不能为空", 400
        # 返回请求数据
        return value.dict(), 200

    def model_validate(
            cls,
            obj: Any,
            *,
            strict: bool | None = None,
            from_attributes: bool | None = None,
            context: Any | None = None,
    ) -> Self:
        if obj.versionCode == '' or obj.versionCode is None:
            return "版本号不能为空", 400
        elif obj.apkUrl == '' or obj.apkUrl is None:
            return "apk下载地址不能为空", 400
        elif obj.wgtUrl == '' or obj.wgtUrl is None:
            return "wgt下载地址不能为空", 400
        # 判断重复
        if AppVersion.objects.filter(versionCode=obj.versionCode, app_id=obj.app_id).exists():
            return "版本号已存在，请重新输入", 400
        # 返回请求数据
        return obj.dict(), 200

    class Config:
        title = '创建应用版本参数'
        model = AppVersion
        model_exclude = ['id', 'creator', 'modifier', 'create_time', 'update_time', 'app']


class FormalAppVersionSchemaIn(Schema):
    appId: int = Field(None, description="应用id", alias="appId")
    versionId: int = Field(None, description="版本id", alias="versionId")

    def validate(cls, value: Any) -> Self:
        if value.appId == '' or value.appId is None:
            return "应用id不能为空", 400
        elif value.versionId == '' or value.versionId is None:
            return "版本id不能为空", 400
        # 返回请求数据
        return value, 200

    class Config:
        title = '设置正式版参数'


class AppVersionSchemaOut(ModelSchema):
    app_id: int = Field(None, description="应用详情ID", alias='app_id')

    class Config:
        title = '应用版本对象实例'
        model = AppVersion
        model_fields = "__all__"


@router.post("/version/add", response=AppVersionSchemaOut, summary="创建应用版本")
def create_version(request: Any, data: AppVersionSchemaIn) -> SuccessResponse | ErrorResponse:
    """ 创建应用版本 """
    message, code = data.model_validate(data)
    if code == 400:
        return ErrorResponse(msg=message)
    # 调用新增方法
    result = create(request, AppVersion, message)
    # 返回结果
    return SuccessResponse(data=result, msg="新增成功")


@router.delete("/version/del/{uuid}", response=AppVersionSchemaOut, summary="删除应用版本")
def delete_app_version(request: Any, uuid: int) -> SuccessResponse | ErrorResponse:
    """ 删除应用版本 """
    # 如果设置了正式版则不能删除
    version = AppVersion.objects.get(id=uuid)
    if version.formalVersion:
        return ErrorResponse(msg="当前版本为正式版，暂不支持删除，如若删除，请删除应用")
    # 调用删除方法
    result, code = delete(AppVersion, uuid)
    if code != 200:
        return ErrorResponse(code=code, msg=result)
    # 返回结果
    return SuccessResponse(data=result, msg="删除成功")


@router.put("/version/update/{uuid}", response=AppVersionSchemaOut, summary="更新应用版本")
def update_app_version(request: Any, uuid: int, data: AppVersionSchemaIn) -> SuccessResponse | ErrorResponse:
    """ 更新应用版本 """
    message, code = data.validate(data)
    if code == 400:
        return ErrorResponse(msg=message)
    # 判断重复
    if AppVersion.objects.filter(versionCode=message['versionCode'], app_id=message['app_id']).exclude(id=uuid).exists():
        return ErrorResponse(msg="版本号已存在，请重新输入")
    # 版本号不支持更新
    del message['versionCode']
    # 调用修改方法
    result = update(request, AppVersion, message, uuid)
    # 返回结果
    return SuccessResponse(data=result, msg="更新成功")


@router.put("/version/appFormal", response=AppVersionSchemaOut, summary="设置正式版")
def formal_app_version(request: Any, data: FormalAppVersionSchemaIn) -> SuccessResponse | ErrorResponse:
    """ 设置正式版 """
    message, code = data.validate(data)
    if code == 400:
        return ErrorResponse(msg=message)
    # 判断当前是否已经设置过正式版
    formal_version_obj = AppVersion.objects.filter(app_id=message.appId, formalVersion=True).first()
    if formal_version_obj:
        # 设置的版本对象
        update_obj = AppVersion.objects.get(id=message.versionId, app_id=message.appId)
        # 比较版本大小
        result = compare_version(update_obj.versionCode, formal_version_obj.versionCode)
        if result == -1:
            return ErrorResponse(code=400, msg="当前版本低于正式版，暂不支持回退版本")
        elif result == 0:
            return ErrorResponse(code=400, msg="当前版本和正式版相同，该操作无效")
    # 将当前应用所有版本锁定
    for version in AppVersion.objects.filter(app_id=message.appId):
        version.formalVersion = False
        version.save()
    # 将当前版本设置为正式
    version = AppVersion.objects.get(id=message.versionId, app_id=message.appId)
    version.formalVersion = True
    version.save()
    # 设置应用正式版
    app = AppDetails.objects.get(id=message.appId)
    app.appVersion_id = version.id
    app.versionCode = version.versionCode
    app.save()
    result, code = single(request, AppVersion, [], version.id)
    # 返回结果
    return result


@router.get("/version/listAll", response=List[AppVersionSchemaOut], summary="获取应用版本所有列表")
def list_all_app_version(request: Any, filters: Filters = Query(...)) -> SuccessResponse | ErrorResponse:
    """ 获取应用版本所有列表 """
    # 调用列表通用方法
    result = retrieve(request, AppVersion, [], filters)
    # 返回结果
    return result


@router.get("/version/getById/{uuid}", response=AppVersionSchemaOut, summary="获取应用版本")
def get_app_version(request: Any, uuid: int) -> SuccessResponse | ErrorResponse:
    """ 获取应用版本 """
    # 调用根据id获取指定对象方法
    result, code = single(request, AppVersion, [], uuid)
    if code != 200:
        return ErrorResponse(code=code, msg=result)
    # 返回结果
    return result
